package cn.iocoder.yudao.framework.common.util.validation;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import org.springframework.util.StringUtils;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * 校验工具类
 *
 * @author 芋道源码
 */
public class ValidationUtils {

    private static final Pattern PATTERN_MOBILE = Pattern.compile("^(?:(?:\\+|00)86)?1(?:(?:3[\\d])|(?:4[0,1,4-9])|(?:5[0-3,5-9])|(?:6[2,5-7])|(?:7[0-8])|(?:8[\\d])|(?:9[0-3,5-9]))\\d{8}$");

    private static final Pattern PATTERN_URL = Pattern.compile("^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]");

    private static final Pattern PATTERN_XML_NCNAME = Pattern.compile("[a-zA-Z_][\\-_.0-9_a-zA-Z$]*");

    public static boolean isMobile(String mobile) {
        return StringUtils.hasText(mobile)
                && PATTERN_MOBILE.matcher(mobile).matches();
    }

    public static boolean isURL(String url) {
        return StringUtils.hasText(url)
                && PATTERN_URL.matcher(url).matches();
    }

    public static boolean isXmlNCName(String str) {
        return StringUtils.hasText(str)
                && PATTERN_XML_NCNAME.matcher(str).matches();
    }
    /**
     * 对对象进行参数校验，使用默认的 Validator 实例。
     *
     * @param object 被校验的对象，通常是使用了 javax.validation 注解的 Bean。
     * @param groups 校验分组，可选。如果不传，则使用默认分组。
     * @throws ConstraintViolationException 如果校验不通过，将抛出该异常，包含所有违反约束的字段信息。
     */
    public static void validate(Object object, Class<?>... groups) {
        // 获取默认的 Validator 实例（线程安全，推荐复用）
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        // 使用 Spring 的 Assert 工具类校验非空
        Assert.notNull(validator);
        // 调用重载方法执行校验
        validate(validator, object, groups);
    }
    /**
     * 使用指定的 Validator 实例对对象进行参数校验。
     *
     * @param validator Validator 实例，来自 Hibernate Validator 或其他实现
     * @param object 被校验的对象，不能为 null，通常是带有 @NotNull、@Size 等注解的 Bean
     * @param groups 分组校验类，可变参数；例如 Default.class 或自定义校验组
     * @throws ConstraintViolationException 如果对象中任意字段校验失败，抛出此异常
     */
    public static void validate(Validator validator, Object object, Class<?>... groups) {
        // 调用 validator 进行校验，返回违反约束的字段集合
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
        // 使用 Hutool 的工具类判断是否非空，如果有错误，抛出异常
        if (CollUtil.isNotEmpty(constraintViolations)) {
            // 抛出包含所有字段错误信息的异常
            throw new ConstraintViolationException(constraintViolations);
        }
    }

}
